from __future__ import absolute_import
from datetime import datetime, timedelta
from calendar import monthrange
import time
import uuid
import json

from tzlocal import get_localzone


class CalendarService(object):
    """
    The 'Calendar' iCloud service, connects to iCloud and returns events.
    """
    def __init__(self, service_root, session, params):
        self.session = session
        self.params = params
        self._service_root = service_root
        self._calendar_endpoint = '%s/ca' % self._service_root
        self._calendar_refresh_url = '%s/events' % self._calendar_endpoint
        self._calendar_event_detail_url = '%s/eventdetail' % (
            self._calendar_endpoint,
        )

    def get_detail(self, pguid, guid):
        """
        Fetches a single event's details by specifying a pguid
        (a calendar) and a guid (an event's ID).
        """
        params = dict(self.params)
        params.update({'lang': 'en-us', 'usertz': get_localzone().zone})
        url = '%s/%s/%s' % (self._calendar_event_detail_url, pguid, guid)
        req = self.session.get(url, params=params)
        self.response = req.json()
        return self.response

    def get_event_detail(self, pguid, guid):
        """
        Fetches a single event's details by specifying a pguid
        (a calendar) and a guid (an event's ID).
        """
        params = dict(self.params)
        params.update({'lang': 'en-us', 'usertz': get_localzone().zone})
        url = '%s/%s/%s' % (self._calendar_event_detail_url, pguid, guid)
        req = self.session.get(url, params=params)
        self.response = req.json()
        return self.response['Event'][0]

    def refresh_client(self, from_dt=None, to_dt=None):
        """
        Refreshes the CalendarService endpoint, ensuring that the
        event data is up-to-date. If no 'from_dt' or 'to_dt' datetimes
        have been given, the range becomes this month.
        """
        today = datetime.today()
        first_day, last_day = monthrange(today.year, today.month)
        if not from_dt:
            from_dt = datetime(today.year, today.month, first_day)
        if not to_dt:
            to_dt = datetime(today.year, today.month, last_day)
        params = dict(self.params)
        params.update({
            'lang': 'en-us',
            'usertz': get_localzone().zone,
            'startDate': from_dt.strftime('%Y-%m-%d'),
            'endDate': to_dt.strftime('%Y-%m-%d')
        })
        req = self.session.get(self._calendar_refresh_url, params=params)
        self.response = req.json()

    def events(self, from_dt=None, to_dt=None):
        """
        Retrieves events for a given date range, by default, this month.
        """
        self.refresh_client(from_dt, to_dt)
        return self.response['Event']

    def refresh(self):
        params_calendars = dict(self.params)
        params_calendars.update({
            'clientVersion': '4.0',
            'lang': 'en-us',
            'usertz': get_localzone().zone,
            'startDate': '2016-09-28',
            'endDate': '2016-10-04'
        })

        # Open reminders
        req = self.session.get(
            self._service_root + '/ca/startup',
            params=params_calendars
        )

        startup = req.json()
        self.collections = {}
        for collection in startup['Collection']:
            temp = []
            self.collections[collection['title']] = {
                'guid': collection['guid'],
                'ctag': collection['ctag']
            }

    def post(self, pguid, title, location="", startDate=None, endDate=None, invitees=None):

        """
        Fetches a single event's details by specifying a pguid
        (a calendar) and a guid (an event's ID).
        """
        self.refresh()

        begs = startDate.split(' ')
        beg_date = ''.join(begs[0].split('/'))
        beg_year = int(begs[0].split('/')[0])
        beg_month = int(begs[0].split('/')[1])
        beg_day = int(begs[0].split('/')[2])

        beg_hour = int(begs[1].split(':')[0])
        beg_min = int(begs[1].split(':')[1])

        ends = endDate.split(' ')
        end_date = ''.join(ends[0].split('/'))
        end_year = int(ends[0].split('/')[0])
        end_month = int(ends[0].split('/')[1])
        end_day = int(ends[0].split('/')[2])

        end_hour = int(ends[1].split(':')[0])
        end_min = int(ends[1].split(':')[1])

        startDate = [beg_date, beg_year,beg_month,beg_day,beg_hour,beg_min,0,0 ]
        endDate = [end_date, end_year,end_month,end_day,end_hour,end_min,0,0 ]

        calendar_guid = str(uuid.uuid4()).upper()

        invitee_objs = []
        invitee_uids = []
        for i in invitees:
            invitee_guid = str(uuid.uuid4()).upper()
            invitee_objs.append({
                "pGuid": calendar_guid,
                "email": i,
                "role": "REQ-PARTICIPANT",
                "inviteeStatus": "NEEDS-ACTION",
                "isMe": False,
                "isOrganizer": False,
                "guid": invitee_guid
            })
            invitee_uids.append(invitee_guid)

        data = {
            "Event": {
                'title': title,
                "location": location,
                "extendedDetailsAreIncluded": True,
                "pGuid": pguid,
                "localStartDate":startDate,
                "localEndDate":endDate,
                "startDate":startDate,
                "endDate":endDate,
                "allDay": False,
                "duration": 60,
                "guid": calendar_guid,
                "recurrenceMaster": False,
                "recurrenceException": False,
                "icon": 0,
                "hasAttachments": False,
                "invitees": invitee_uids,
                "changeRecurring": None,
                "createdDateExtended": int(time.time()*1000),
            },
            "Invitee": invitee_objs,
            "ClientState": {
                "Collections": list(self.collections.values()) ,
                "fullState": False,
                "userTime": 1234567890,
                "alarmRange": 60
            }
        }

        params = dict(self.params)
        params.update({
            'lang': 'en-us',
            'usertz': get_localzone().zone,
            #'startDate': '2016-08-28',
            #'endDate': '2016-10-04',
            'clientVersion': '5.1'
        })
        url = '%s/%s/%s' % (self._calendar_refresh_url, pguid, calendar_guid)

        req = self.session.post(
            url,
            data=json.dumps(data),
            params=params)

        return calendar_guid
